package com.airlines.base.config.cglib;

import java.beans.PropertyDescriptor;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.beanutils.PropertyUtilsBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author xxxx
 * @date 2018年6月15日
 * @description
 * @see https://www.cnblogs.com/frinder6/p/7204574.html
 * @see https://blog.csdn.net/ajun_studio/article/details/6807181
 */
public class ReflectUtil {
	private static Logger logger = LoggerFactory.getLogger(ReflectUtil.class);

	@SuppressWarnings("rawtypes")
	public static Object getTarget(Object dest, Map<String, Object> addProperties) {
		// get property map
		Map<String, Class> addPropertyMap = new HashMap<>();
		// add extra properties
		addProperties.forEach((k, v) -> addPropertyMap.put(k, v.getClass()));
		// new dynamic bean
		DynamicBean dynamicBean = new DynamicBean(dest.getClass(), addPropertyMap);

		// add old value
		PropertyUtilsBean propertyUtilsBean = new PropertyUtilsBean();
		PropertyDescriptor[] descriptors = propertyUtilsBean.getPropertyDescriptors(dest);
		Map<String, Class> oldPropertyMap = new HashMap<>();
		for (PropertyDescriptor d : descriptors) {
			if (!"class".equalsIgnoreCase(d.getName())) {
				oldPropertyMap.put(d.getName(), d.getPropertyType());
			}
		}
		oldPropertyMap.forEach((k, v) -> {
			try {
				// filter extra properties
				if (!addProperties.containsKey(k)) {
					dynamicBean.setValue(k, propertyUtilsBean.getNestedProperty(dest, k));
				}
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		});

		// add new value
		addProperties.forEach((k, v) -> {
			try {
				dynamicBean.setValue(k, v);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
		});
		Object target = dynamicBean.getTarget();
		return target;
	}

}
